package com.bigflexlib.x.mx.collections.IList.op
{
	
	import flash.utils.Dictionary;
	
	import mx.collections.IList;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	
	import com.bigflexlib.x.mx.collections.IList.IListUtil;

	
	
	public class ListMappingOp extends AbstractListToListOp
	{
		
		
		
		private var iMappingFunction:Function;

		
		private var mapCache:Dictionary;		
		
		
		/**
		 * 
		 * @param iList
		 * @param oList
		 * @param iMappingFunction
		 * 		If no mapping function is passed, then items are just copied over.
		 * 		This way you can keep two different lists sync'ed
		 * 
		 * @param iCacheMappingResult
		 * 
		 */		
		public function ListMappingOp( iList:IList, oList:IList, iMappingFunction:Function = null, iCacheMappingResult:Boolean = false )
		{
			super( iList, oList );
			
			this.iMappingFunction = iMappingFunction;

			
			if ( iCacheMappingResult )
			{
				mapCache = new Dictionary( );
			}
			
			
			refresh( );
		
		}
		
		
		
		
		private function refresh( ):void
		{
			
			IListUtil.autoUpdate( oList, false );			

			oList.removeAll();

			var inputItems:Array = iList.toArray( );

			for each ( var item:Object in inputItems )
			{
				oList.addItem( mapItem( item ) ); 				
			}
			
			IListUtil.autoUpdate( oList, true );			

		}		
		
		
		
		
		
		private function mapItem( item:* ):* 
		{
			
			
			if ( iMappingFunction == null ) // passthru mode
			{
				return item;			
			}
			
			
			
			
			if ( mapCache != null ) // use cache
			{
			
				if ( mapCache[ item ] === undefined )
				{
					mapCache[ item ] = iMappingFunction.call( null, item )
				}

				return mapCache[ item ];			
			}
			
			
			return iMappingFunction.call( null, item );
		}
		



		
		
		
		override protected function iList_collectionChange( event:CollectionEvent ):void
		{
		

			IListUtil.autoUpdate( oList, false );		
			

	        switch ( event.kind )
	        {
	            
	            case CollectionEventKind.ADD:

					
				
					for ( var i:int=0 ; i < event.items.length ; i++ )
					{
						oList.addItemAt(  mapItem( event.items[i] ), event.location + i );
					}
						            
	            break;
	            
	            
	            
	            case CollectionEventKind.REMOVE:


					for ( var j:int=0 ; j < event.items.length ; j++ )
					{
						oList.removeItemAt( event.location );
					}				
	            
	            break;

	
	            case CollectionEventKind.RESET:
	            
	                refresh( );
	            
	            break;


	            case CollectionEventKind.REFRESH:
	            
	                refresh( );

	            break;
	
	        }
	        
			IListUtil.autoUpdate( oList, true );				
		
		
		}
		
		
		
		
		
		
		
		
		
		override public function dispose( ):void
		{
			
			super.dispose( );
			
			iMappingFunction = null;
			
			mapCache = null;
			
		
		}
		
		
		
		
		
		
	}
}